/**
 * Project  : Looker
 * Package  : net.freestu.looker.monitor
 * File     : FileFetcher.java
 * Author   : solosky < solosky772@qq.com >
 * Date     : Aug 23, 2009
 * Modified : Aug 23, 2009
 * License  : Apache License 2.0 
 */
package net.freestu.looker.monitor;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.freestu.looker.common.Looker;
import net.freestu.looker.common.Media;
import net.freestu.looker.util.URLUtils;

import org.apache.log4j.Logger;



/**
 *  文件下载器
 *  下载网页上的文件
 */
public class FileFetcher extends AbstractFetcher
{

	/**
	 * 下载的附件
	 */
	private Media media;
	
	 /**
	  * 日志记录
	  */
	
	private static Logger logger = Logger.getLogger(FileFetcher.class);
	/**
	 * 只有地址的构造函数
     * @param surl
     * @throws FetcherException
     */
    public FileFetcher(String surl) throws FetcherException
    {
	    super(surl);
	    media = new Media();
	    media.setUrl(surl);
	    media.setDate(new Date());
    }
    
    /**
     * 附件和闭锁的构造函数
     * @param surl
     * @param latch
     * @throws FetcherException
     */
    public FileFetcher(Media media, CountDownLatch latch) throws FetcherException
    {
    	super(media.getUrl(),latch);
    	this.media = media;
    }
    
   /**
    * 只有附件的构造函数 
    * @param media
    * @throws FetcherException
    */
   public FileFetcher(Media media) throws FetcherException
   {
	   super(media.getUrl());
	   this.media = media;
   }

	/* (non-Javadoc)
     * @see net.freestu.looker.monitor.AbstractFetcher#fetch()
     */
    @Override
    public void fetch() throws FetcherException
    {
    	logger.debug("开始下载文件:" +url);
	    openConnection();
	    checkContentType();
	    saveFile();
	    
    }

	/* (non-Javadoc)
     * @see net.freestu.looker.monitor.AbstractFetcher#getFeched()
     */
    @Override
    public Object getFeched()
    {
	    return media;
    }
    
    /**
     * 检查Header中的ContentType是否是可下载的文件
     * @throws FetcherException 
     */
    private void checkContentType() throws FetcherException
    {
    	String type = connection.getContentType();
    	if (type.equals("text/html"))
    	{
    		isSuccess = false;
    		throw new FetcherException("下载文件类型错误:"+url+" - "+type);
    	}
    }
    
    /**
	 * 保存文件
     * @throws FetcherException 
	 */
	private void saveFile() throws FetcherException
	{
		//建立文件开始保存下载的文件
		File saveFile = getTmpFile();
		
		//打开文件，开始读取服务器文件内容
		//获取网络输入流
		try {
	    BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
	    //建立文件
	    FileOutputStream fos = new FileOutputStream(saveFile);
	    //保存文件
	    int size = 0;
	    byte[] buf = new byte[255];
	    
	    while ( (size = bis.read(buf)) != -1) 
	      fos.write(buf, 0, size);
	    
	    fos.close();
	    bis.close();
		}catch(IOException e) {
			throw new FetcherException(e.getMessage());
		}
		
	    //填写文件一些信息
		media.setSize((int)saveFile.length());
		media.setTmpFile(saveFile);		
	}
	
	/**
	 * 返回临时文件,准备写入
	 * @throws FetcherException 
	 */
	private File getTmpFile() throws FetcherException
	{
		StringBuffer path = new StringBuffer();
		path.append(Looker.gloalConfig.getString("looker.tmpMediaDir"));
		path.append(System.currentTimeMillis());
		path.append('-');
		//文件名
		//检查返回的头部信息是否有Content-Disposition: attachment; filename="TPtpl.rar"
		//如果有，以此文件名代替原来的文件名
		String disp = connection.getHeaderField("Content-Disposition");
		if(disp!=null)
		{
			String regex = "^.*?filename=['\"](.*?)['\"]^";
			Pattern pt = Pattern.compile(regex);
			Matcher mc = pt.matcher(disp);
			if(mc.matches()) {
			path.append(mc.group(1));
			//更新保存的文件名
			//NOTE:这里数据库里保存的是没有加时间前缀的文件名
			media.setName(mc.group(1));
			}else {
				path.append(URLUtils.file(url.toString()));
			}
		}else {
			path.append(URLUtils.file(url.toString()));
		}
		
		File tmpFile = new File(path.toString());
		
		try {
		if(!tmpFile.exists())
	        tmpFile.createNewFile();
        } catch (IOException e) {
        	throw new FetcherException(e.getMessage()+" : " +tmpFile);
        }
        
		if(!tmpFile.canWrite())
			throw new FetcherException("临时文件不能能写入:"+path);
		else 
			return tmpFile;
	}
	
}
